// Copyright 2021 ETH Zurich and University of Bologna.
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
// SPDX-License-Identifier: SHL-0.51
//
// Author: Matteo Perotti <mperotti@iis.ee.ethz.ch>
//         Basile Bougenot <bbougenot@student.ethz.ch>

#include "vector_macros.h"

void TEST_CASE1(void) {
  VSET(16, e8, m1);
  VLOAD_8(v2, 0x85, 0x1d, 0x9f, 0x31, 0x8c, 0x4c, 0x4c, 0xf2, 0x11, 0xfc, 0xc8,
          0xab, 0xc2, 0xff, 0xf5, 0xc2);
  VLOAD_8(v3, 0x3d, 0x06, 0x32, 0x36, 0x02, 0x0f, 0x27, 0x35, 0x1e, 0x0f, 0x36,
          0x1c, 0x24, 0x1a, 0x22, 0x01);
  asm volatile("vdivu.vv v1, v2, v3");
  VCMP_I8(1, v1, 0x02, 0x04, 0x03, 0x00, 0x46, 0x05, 0x01, 0x04, 0x00, 0x10,
          0x03, 0x06, 0x05, 0x09, 0x07, 0xc2);

  VSET(16, e16, m1);
  VLOAD_16(v2, 0xd200, 0xa047, 0x7af8, 0x453d, 0xd6eb, 0xfabb, 0x604a, 0xea35,
           0xbc2d, 0x45e7, 0x8407, 0x3845, 0x1495, 0x8ee6, 0x7da4, 0xf34a);
  VLOAD_16(v3, 0x03ad, 0x00b8, 0x001b, 0x0353, 0x013f, 0x008c, 0x015e, 0x01e6,
           0x00cd, 0x0093, 0x00ba, 0x03d0, 0x0117, 0x009d, 0x007b, 0x02cf);
  asm volatile("vdivu.vv v1, v2, v3");
  VCMP_I16(2, v1, 0x0039, 0x00de, 0x048d, 0x0014, 0x00ac, 0x01ca, 0x0046,
           0x007b, 0x00ea, 0x0079, 0x00b5, 0x000e, 0x0012, 0x00e9, 0x0105,
           0x0056);

  VSET(16, e32, m1);
  VLOAD_32(v2, 0xd56bd03a, 0x1036c5ff, 0xaa01847f, 0x988dc35d, 0x4d8615dc,
           0xb62269e2, 0xe842ba75, 0x02fecbf9, 0xe536c712, 0xe93e2160,
           0x9ba34297, 0x554d290d, 0x319f668c, 0x0d6c2fbb, 0x6a7eb54a,
           0x3fa1cc84);
  VLOAD_32(v3, 0x00000025, 0x00000057, 0x0000002e, 0x0000004c, 0x00000052,
           0x00000021, 0x0000001d, 0x0000002f, 0x00000029, 0x00000008,
           0x00000015, 0x00000029, 0x00000048, 0x00000051, 0x0000003f,
           0x00000007);
  asm volatile("vdivu.vv v1, v2, v3");
  VCMP_I32(3, v1, 0x05c4a4c3, 0x002fb5c5, 0x03b21eb4, 0x0201dd84, 0x00f20682,
           0x0584ebef, 0x08024d0c, 0x00105098, 0x05973090, 0x1d27c42c,
           0x07694c50, 0x02149d19, 0x00b06fa5, 0x002a6c0b, 0x01b0bdcc,
           0x09171d37);

  VSET(16, e64, m1);
  VLOAD_64(v2, 0xf251717441f02108, 0x2668b5d7f073b9d1, 0x4708b49fd356a60a,
           0x195bedcb9ce5956b, 0x41ce2b35b4280568, 0x32e5b89eed21de3b,
           0x73f17f3d0e1f243f, 0x0d0aa119af3b0e95, 0x024cbba6ba662213,
           0xf7df98f44da5e55f, 0x3cf2951aa7e4c0a9, 0x0ed8987446e84f30,
           0xd983a7a0d4c648b4, 0x60eb8249069801a5, 0x529967e8b06df477,
           0x776410b4b0cc22ad);
  VLOAD_64(v3, 0x000000000000695b, 0x0000000000007420, 0x000000000001850c,
           0x000000000000b46f, 0x000000000000e92c, 0x0000000000024e72,
           0x0000000000032774, 0x000000000001c36f, 0x00000000000063d2,
           0x0000000000037bb4, 0x000000000003692c, 0x000000000001d60c,
           0x000000000002cf7b, 0x0000000000037899, 0x0000000000038bcf,
           0x000000000003d0e4);
  asm volatile("vdivu.vv v1, v2, v3");
  VCMP_I64(4, v1, 0x00024ccd25dd5faf, 0x000054ac6a930494, 0x00002ebddee9df57,
           0x000023fac7321f85, 0x0000483f73b2e3e2, 0x000016114f5d8a9e,
           0x000024c26869df0e, 0x00000765470f410f, 0x000005e5de9b769d,
           0x0000472988fa89c3, 0x000011de6d57a394, 0x00000815e7b8df73,
           0x00004d64ede3b4a6, 0x00001bec0e79307a, 0x0000174af5139f58,
           0x00001f497ec0ff30);
};

void TEST_CASE2(void) {
  VSET(16, e8, m1);
  VLOAD_8(v2, 0x85, 0x1d, 0x9f, 0x31, 0x8c, 0x4c, 0x4c, 0xf2, 0x11, 0xfc, 0xc8,
          0xab, 0xc2, 0xff, 0xf5, 0xc2);
  VLOAD_8(v3, 0x3d, 0x06, 0x32, 0x36, 0x02, 0x0f, 0x27, 0x35, 0x1e, 0x0f, 0x36,
          0x1c, 0x24, 0x1a, 0x22, 0x01);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vv v1, v2, v3, v0.t");
  VCMP_I8(5, v1, 0, 0x04, 0, 0x00, 0, 0x05, 0, 0x04, 0, 0x10, 0, 0x06, 0, 0x09,
          0, 0xc2);

  VSET(16, e16, m1);
  VLOAD_16(v2, 0xd200, 0xa047, 0x7af8, 0x453d, 0xd6eb, 0xfabb, 0x604a, 0xea35,
           0xbc2d, 0x45e7, 0x8407, 0x3845, 0x1495, 0x8ee6, 0x7da4, 0xf34a);
  VLOAD_16(v3, 0x03ad, 0x00b8, 0x001b, 0x0353, 0x013f, 0x008c, 0x015e, 0x01e6,
           0x00cd, 0x0093, 0x00ba, 0x03d0, 0x0117, 0x009d, 0x007b, 0x02cf);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vv v1, v2, v3, v0.t");
  VCMP_I16(6, v1, 0, 0x00de, 0, 0x0014, 0, 0x01ca, 0, 0x007b, 0, 0x0079, 0,
           0x000e, 0, 0x00e9, 0, 0x0056);

  VSET(16, e32, m1);
  VLOAD_32(v2, 0xd56bd03a, 0x1036c5ff, 0xaa01847f, 0x988dc35d, 0x4d8615dc,
           0xb62269e2, 0xe842ba75, 0x02fecbf9, 0xe536c712, 0xe93e2160,
           0x9ba34297, 0x554d290d, 0x319f668c, 0x0d6c2fbb, 0x6a7eb54a,
           0x3fa1cc84);
  VLOAD_32(v3, 0x00000025, 0x00000057, 0x0000002e, 0x0000004c, 0x00000052,
           0x00000021, 0x0000001d, 0x0000002f, 0x00000029, 0x00000008,
           0x00000015, 0x00000029, 0x00000048, 0x00000051, 0x0000003f,
           0x00000007);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vv v1, v2, v3, v0.t");
  VCMP_I32(7, v1, 0, 0x002fb5c5, 0, 0x0201dd84, 0, 0x0584ebef, 0, 0x00105098, 0,
           0x1d27c42c, 0, 0x02149d19, 0, 0x002a6c0b, 0, 0x09171d37);

  VSET(16, e64, m1);
  VLOAD_64(v2, 0xf251717441f02108, 0x2668b5d7f073b9d1, 0x4708b49fd356a60a,
           0x195bedcb9ce5956b, 0x41ce2b35b4280568, 0x32e5b89eed21de3b,
           0x73f17f3d0e1f243f, 0x0d0aa119af3b0e95, 0x024cbba6ba662213,
           0xf7df98f44da5e55f, 0x3cf2951aa7e4c0a9, 0x0ed8987446e84f30,
           0xd983a7a0d4c648b4, 0x60eb8249069801a5, 0x529967e8b06df477,
           0x776410b4b0cc22ad);
  VLOAD_64(v3, 0x000000000000695b, 0x0000000000007420, 0x000000000001850c,
           0x000000000000b46f, 0x000000000000e92c, 0x0000000000024e72,
           0x0000000000032774, 0x000000000001c36f, 0x00000000000063d2,
           0x0000000000037bb4, 0x000000000003692c, 0x000000000001d60c,
           0x000000000002cf7b, 0x0000000000037899, 0x0000000000038bcf,
           0x000000000003d0e4);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vv v1, v2, v3, v0.t");
  VCMP_I64(8, v1, 0, 0x000054ac6a930494, 0, 0x000023fac7321f85, 0,
           0x000016114f5d8a9e, 0, 0x00000765470f410f, 0, 0x0000472988fa89c3, 0,
           0x00000815e7b8df73, 0, 0x00001bec0e79307a, 0, 0x00001f497ec0ff30);
};

void TEST_CASE3(void) {
  VSET(16, e8, m1);
  VLOAD_8(v2, 0x0f, 0xbd, 0x0a, 0x58, 0x8e, 0x09, 0xa7, 0x02, 0x4b, 0xe8, 0xd2,
          0xfc, 0xa9, 0x8e, 0x67, 0x49);
  uint64_t scalar = 5;
  asm volatile("vdivu.vx v1, v2, %[A]" ::[A] "r"(scalar));
  VCMP_I8(9, v1, 0x03, 0x25, 0x02, 0x11, 0x1c, 0x01, 0x21, 0x00, 0x0f, 0x2e,
          0x2a, 0x32, 0x21, 0x1c, 0x14, 0x0e);

  VSET(16, e16, m1);
  VLOAD_16(v2, 0xcf2f, 0x0c02, 0x1417, 0x1747, 0x5e43, 0x9552, 0xe03e, 0x5367,
           0xb2f9, 0x09d8, 0x3b19, 0x8ed0, 0x4740, 0xa628, 0x5560, 0x713b);
  scalar = 538;
  asm volatile("vdivu.vx v1, v2, %[A]" ::[A] "r"(scalar));
  VCMP_I16(10, v1, 0x0062, 0x0005, 0x0009, 0x000b, 0x002c, 0x0047, 0x006a,
           0x0027, 0x0055, 0x0004, 0x001c, 0x0043, 0x0021, 0x004f, 0x0028,
           0x0035);

  VSET(16, e32, m1);
  VLOAD_32(v2, 0x643498d4, 0xe1e4c6d4, 0x2fef6b6f, 0xe68ef651, 0x9943599a,
           0x68af922e, 0x09a3beb2, 0x117ff561, 0x86a1a3f7, 0x03566f4f,
           0xc3c0c7de, 0x8cb524f8, 0x532e1652, 0xb0c26bf2, 0x886d0b1c,
           0xf94d6b63);
  scalar = 649;
  asm volatile("vdivu.vx v1, v2, %[A]" ::[A] "r"(scalar));
  VCMP_I32(11, v1, 0x002786be, 0x00591abc, 0x0012e87f, 0x005af1c8, 0x003c7480,
           0x00294b2b, 0x0003cd68, 0x0006e722, 0x00351b13, 0x00015108,
           0x004d3723, 0x003780a6, 0x0020cf84, 0x0045b92a, 0x0035d049,
           0x0062568c);

  VSET(16, e64, m1);
  VLOAD_64(v2, 0x751ea878eaf9f85f, 0x9843aba4c3e313af, 0xc2f56d78083dc0f2,
           0x4fcb920a2a4ebc8d, 0x33a71e7364643a7c, 0x76f96f8403af4ad7,
           0xcdbbb2002ea6ac93, 0xc380d0b6a5182bcc, 0x93b79fcc64af88cf,
           0x85d32b075e613f6c, 0x4f1f75bfa6d8f319, 0xd2a34a8d9a02d7f1,
           0x8679a27b237a032e, 0x7e0881a487bbb235, 0x17d97d9849271cec,
           0x1c85ac87ba3c7d1e);
  scalar = 9223;
  asm volatile("vdivu.vx v1, v2, %[A]" ::[A] "r"(scalar));
  VCMP_I64(12, v1, 0x000340383152452b, 0x000439f263aaf34a, 0x000569521e089c7c,
           0x0002370079144c76, 0x00016f07b37c5546, 0x00034d65d36c535c,
           0x0005b5e194247d88, 0x00056d3090f69ef0, 0x000419a3026cfde7,
           0x0003b6ebd974c870, 0x000232398140d5dd, 0x0005d8bb7bec2e99,
           0x0003bb8ab6abb03a, 0x00037f8e5aab0783, 0x0000a977deb32c78,
           0x0000caab9b4a8885);
};

void TEST_CASE4(void) {
  VSET(16, e8, m1);
  VLOAD_8(v2, 0x0f, 0xbd, 0x0a, 0x58, 0x8e, 0x09, 0xa7, 0x02, 0x4b, 0xe8, 0xd2,
          0xfc, 0xa9, 0x8e, 0x67, 0x49);
  uint64_t scalar = 5;
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vx v1, v2, %[A], v0.t" ::[A] "r"(scalar));
  VCMP_I8(13, v1, 0, 0x25, 0, 0x11, 0, 0x01, 0, 0x00, 0, 0x2e, 0, 0x32, 0, 0x1c,
          0, 0x0e);

  VSET(16, e16, m1);
  VLOAD_16(v2, 0xcf2f, 0x0c02, 0x1417, 0x1747, 0x5e43, 0x9552, 0xe03e, 0x5367,
           0xb2f9, 0x09d8, 0x3b19, 0x8ed0, 0x4740, 0xa628, 0x5560, 0x713b);
  scalar = 538;
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vx v1, v2, %[A], v0.t" ::[A] "r"(scalar));
  VCMP_I16(14, v1, 0, 0x0005, 0, 0x000b, 0, 0x0047, 0, 0x0027, 0, 0x0004, 0,
           0x0043, 0, 0x004f, 0, 0x0035);

  VSET(16, e32, m1);
  VLOAD_32(v2, 0x643498d4, 0xe1e4c6d4, 0x2fef6b6f, 0xe68ef651, 0x9943599a,
           0x68af922e, 0x09a3beb2, 0x117ff561, 0x86a1a3f7, 0x03566f4f,
           0xc3c0c7de, 0x8cb524f8, 0x532e1652, 0xb0c26bf2, 0x886d0b1c,
           0xf94d6b63);
  scalar = 649;
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vx v1, v2, %[A], v0.t" ::[A] "r"(scalar));
  VCMP_I32(15, v1, 0, 0x00591abc, 0, 0x005af1c8, 0, 0x00294b2b, 0, 0x0006e722,
           0, 0x00015108, 0, 0x003780a6, 0, 0x0045b92a, 0, 0x0062568c);

  VSET(16, e64, m1);
  VLOAD_64(v2, 0x751ea878eaf9f85f, 0x9843aba4c3e313af, 0xc2f56d78083dc0f2,
           0x4fcb920a2a4ebc8d, 0x33a71e7364643a7c, 0x76f96f8403af4ad7,
           0xcdbbb2002ea6ac93, 0xc380d0b6a5182bcc, 0x93b79fcc64af88cf,
           0x85d32b075e613f6c, 0x4f1f75bfa6d8f319, 0xd2a34a8d9a02d7f1,
           0x8679a27b237a032e, 0x7e0881a487bbb235, 0x17d97d9849271cec,
           0x1c85ac87ba3c7d1e);
  scalar = 9223;
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vdivu.vx v1, v2, %[A], v0.t" ::[A] "r"(scalar));
  VCMP_I64(16, v1, 0, 0x000439f263aaf34a, 0, 0x0002370079144c76, 0,
           0x00034d65d36c535c, 0, 0x00056d3090f69ef0, 0, 0x0003b6ebd974c870, 0,
           0x0005d8bb7bec2e99, 0, 0x00037f8e5aab0783, 0, 0x0000caab9b4a8885);
};

int main(void) {
  INIT_CHECK();
  enable_vec();

  TEST_CASE1();
  TEST_CASE2();
  TEST_CASE3();
  TEST_CASE4();

  EXIT_CHECK();
}
